package com.bite.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.bite.blog.api.BlogServiceApi;
import com.bite.blog.api.pojo.BlogInfoResponse;
import com.bite.common.exception.BlogException;
import com.bite.common.pojo.Result;
import com.bite.common.utils.*;
import com.bite.user.api.pojo.UserInfoRegisterRequest;
import com.bite.user.api.pojo.UserInfoRequest;
import com.bite.user.api.pojo.UserInfoResponse;
import com.bite.user.api.pojo.UserLoginResponse;
import com.bite.user.constants.Constants;
import com.bite.user.convert.BeanConvert;
import com.bite.user.dataobject.UserInfo;
import com.bite.user.mapper.UserInfoMapper;
import com.bite.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private BlogServiceApi blogServiceApi;

    @Autowired
    private EncapsulatedRedisTemplate redisTemplate;

    private static final String USER_PREFIX = "USER";

    private static final long EXPIRE_TIME = 14 * 24 * 60 * 60;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public UserLoginResponse login(UserInfoRequest user) {
        //验证账号密码是否正确
        UserInfo userInfo = queryUserInfo(user.getUserName());
        if (userInfo == null || userInfo.getId() == null){
            throw new BlogException("用户不存在");
        }
        if (!SecurityUtil.verify(user.getPassword(),userInfo.getPassword())){
            throw new BlogException("用户密码不正确");
        }
        //账号密码正确的逻辑
        Map<String,Object> claims = new HashMap<>();
        claims.put("id", userInfo.getId());
        claims.put("name", userInfo.getUserName());

        String jwt = JWTUtils.genJwt(claims);
        return new UserLoginResponse(userInfo.getId(), jwt);
    }


    @Override
    public UserInfoResponse getUserInfo(Integer userId) {
        UserInfoResponse userInfoResponse = new UserInfoResponse();
        UserInfo userInfo = selectUserInfoById(userId);
        BeanUtils.copyProperties(userInfo, userInfoResponse);
        return userInfoResponse;
    }

    @Override
    public UserInfoResponse selectAuthorInfoByBlogId(Integer blogId) {
        UserInfoResponse userInfoResponse = new UserInfoResponse();
        //1. 根据博客ID, 获取作者ID
        //远程调用
        Result<BlogInfoResponse> blogInfo = blogServiceApi.getBlogDetail(blogId);
        //2. 根据作者ID, 获取作者信息
        if (blogInfo == null || blogInfo.getData() == null){
            throw new BlogException("博客不存在");
        }
        UserInfo userInfo = selectUserInfoById(blogInfo.getData().getUserId());
        BeanUtils.copyProperties(userInfo, userInfoResponse);
        return userInfoResponse;
    }

    @Override
    public Integer register(UserInfoRegisterRequest registerRequest) {
        //验证
        checkUserInfo(registerRequest);
        //插入数据库
        UserInfo userInfo = BeanConvert.convertToUserInfo(registerRequest);
        try {
            Integer result = userInfoMapper.insert(userInfo);
            if (result == 1) {
                redisTemplate.set(buildUserKey(userInfo.getUserName()), JsonUtil.toJSON(userInfo), EXPIRE_TIME);
                //发送消息(先将密码置空)
                //TODO 更好的解决方案是创建一个mq的信息对象，然后进行convert
                userInfo.setPassword("");
                rabbitTemplate.convertAndSend(Constants.USER_EXCHANGE_NAME, "", JsonUtil.toJSON(userInfo));
                return userInfo.getId();
            } else {
                throw new BlogException("用户注册失败！");
            }
        } catch (Exception e) {
            log.error("用户注册失败, e:", e);
            throw new BlogException("用户注册失败！");
        }
    }

    private String buildUserKey(String userName) {
        return redisTemplate.buildKey(USER_PREFIX, userName);
    }

    private void checkUserInfo(UserInfoRegisterRequest param) {
        UserInfo userInfo = queryUserInfo(param.getUserName());
        if (userInfo != null) {
            throw new BlogException("用户名已存在");
        }
        if (!RegexUtil.checkMail(param.getEmail())) {
            throw new BlogException("邮箱格式不正确");
        }
        if (!RegexUtil.checkUrl(param.getGithubUrl())) {
            throw new BlogException("githubUrl格式不正确");
        }
    }

    private UserInfo queryUserInfo(String userName) {
        String key = buildUserKey(userName);
        boolean isExists = redisTemplate.exists(key);
        if(isExists) {
            String jsonStr = redisTemplate.get(key);
            UserInfo userInfo = JsonUtil.parseJson(jsonStr, UserInfo.class);
            return userInfo == null ? selectUserInfoByName(userName) : userInfo;
        } else {
            UserInfo userInfo = selectUserInfoByName(userName);
            redisTemplate.set(key, JsonUtil.toJSON(userInfo), EXPIRE_TIME);
            return userInfo;
        }
    }
    public UserInfo selectUserInfoByName(String userName) {
        return userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getUserName, userName).eq(UserInfo::getDeleteFlag, 0));
    }
    private UserInfo selectUserInfoById(Integer userId) {
        return userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getId, userId).eq(UserInfo::getDeleteFlag, 0));
    }
}
